<template><h1 id="加餐三-加载阶段性能-使用audits来优化web性能" tabindex="-1"><a class="header-anchor" href="#加餐三-加载阶段性能-使用audits来优化web性能" aria-hidden="true">#</a> 加餐三｜加载阶段性能：使用Audits来优化Web性能</h1>
<p>你好，我是李兵。</p>
<p>作为一名前端工程师，除了需要编写功能性的代码以外，我们还需要关注 Web 应用的性能问题，我们应该有能力让我们的 Web 应用占用最小的资源，并以最高性能运行，这也是前端工程师进阶的必要能力。既然性能这么重要，那么我们今天要来聊聊 Web 性能问题。</p>
<h2 id="到底什么是-web-性能" tabindex="-1"><a class="header-anchor" href="#到底什么是-web-性能" aria-hidden="true">#</a> 到底什么是 Web 性能?</h2>
<p>我们看下 wiki 对 Web 性能的<a href="https://en.wikipedia.org/wiki/Web_performance" target="_blank" rel="noopener noreferrer">定义<ExternalLinkIcon/></a>：</p>
<blockquote>
<p>Web 性能描述了 Web 应用在浏览器上的加载和显示的速度。</p>
</blockquote>
<p>因此，当我们讨论 Web 性能时，其实就是讨论 Web 应用速度，关于 Web 应用的速度，我们需要从两个阶段来考虑：</p>
<ul>
<li>
<p>页面加载阶段；</p>
</li>
<li>
<p>页面交互阶段。</p>
</li>
</ul>
<p>在本文中，我们会将焦点放到第一个阶段：页面加载阶段的性能，在下篇文章中，我们会来重点分析页面交互阶段的性能。</p>
<h2 id="性能检测工具-performance-vs-audits" tabindex="-1"><a class="header-anchor" href="#性能检测工具-performance-vs-audits" aria-hidden="true">#</a> 性能检测工具：Performance vs Audits</h2>
<p>要想优化 Web 的性能，我们就需要有监控 Web 应用的性能数据，那怎么监控呢？</p>
<p>如果没有工具来模拟各种不同的场景并统计各种性能指标，那么定位 Web 应用的性能瓶颈将是一件非常困难的任务。幸好，Chrome 为我们提供了非常完善的性能检测工具：<strong>Performance</strong> 和 <strong>Audits</strong>，它们能够准确统计页面在加载阶段和运行阶段的一些核心数据，诸如任务执行记录、首屏展示花费的时长等，有了这些数据我们就能很容易定位到 Web 应用的<strong>性能瓶颈</strong> 。</p>
<p>首先 Performance 非常强大，因为它为我们提供了非常多的运行时数据，利用这些数据我们就可以分析出来 Web 应用的瓶颈。但是要完全学会其使用方式却是非常有难度的，其难点在于这些数据涉及到了特别多的概念，而这些概念又和浏览器的系统架构、消息循环机制、渲染流水线等知识紧密联系在了一起。</p>
<p>相反，Audtis 就简单了许多，它将检测到的细节数据隐藏在背后，只提供给我们一些直观的性能数据，同时，还会给我们提供一些优化建议。</p>
<p>Perfomance 能让我们看到更多细节数据，但是更加复杂，Audits 就比较智能，但是隐藏了更多细节。为了能够让你循序渐进地理解内容，所以本节我们先从简单的 Audits 入手，看看如何利用它来检测和优化页面在加载阶段的性能，然后在下一节我们再来分析 Perfomance。</p>
<h2 id="检测之前准备工作" tabindex="-1"><a class="header-anchor" href="#检测之前准备工作" aria-hidden="true">#</a> 检测之前准备工作</h2>
<p>不过在检测 Web 的性能指标之前，我们还要配置好工作环境，具体地讲，你需要准备以下内容：</p>
<ul>
<li>
<p>首先准备 Chrome Canary 版的浏览器，Chrome Canary 是采用最新技术构建的，它的开发者工具和浏览器特性都是最新的，所以我推荐你使用 Chrome Canary 来做性能分析。当然你也可以使用稳定版的 Chrome。</p>
</li>
<li>
<p>然后我们需要在 Chrome 的隐身模式下工作，这样可以确保我们安装的扩展、浏览器缓存、Cookie 等数据不会影响到检测结果。</p>
</li>
</ul>
<h2 id="利用-audits-生成-web-性能报告" tabindex="-1"><a class="header-anchor" href="#利用-audits-生成-web-性能报告" aria-hidden="true">#</a> 利用 Audits 生成 Web 性能报告</h2>
<p>环境准备好了之后，我们就可以生成站点在加载阶段的性能报告了，这里我们可以拿B 站作为分析的列子。</p>
<ul>
<li>
<p>首先我们打开浏览器的隐身窗口，Windows 系统下面的快捷键是 Control+Shift+N，Mac 系统下面的快捷键是 Command+Shift+N。</p>
</li>
<li>
<p>然后在隐身窗口中输入 B 站的网站。</p>
</li>
<li>
<p>打开 Chrome 的开发者工具，选择 Audits 标签。</p>
</li>
</ul>
<p>最终打开的页面如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/f4/09/f47e598b2fe371e0af067c74756a8909.png" alt="Audits 界面"></p>
<p>观察上图中的 Audits 界面，我们可以看到，在生成报告之前，我们需要先配置 Audits，配置模块主要有两部分组成，一个是<strong>监测类型 (Categories)</strong>，另外一个是<strong>设备类型 (Device)</strong>。</p>
<p><strong>监控类型 (Categories) 是指需要监控哪些内容</strong>，这里有五个对应的选项，它们的功能分别是：</p>
<ul>
<li>
<p>监测并分析 Web 性能 (<strong>Performance</strong>)；</p>
</li>
<li>
<p>监测并分析 PWA(<strong>Progressive Web App</strong>) 程序的性能；</p>
</li>
<li>
<p>监测并分析 Web 应用是否采用了最佳实践策略 (<strong>Best practices</strong>)；</p>
</li>
<li>
<p>监测并分析是否实施了无障碍功能 (<strong>Accessibility</strong>)，<a href="https://web.dev/accessibility/" target="_blank" rel="noopener noreferrer">无障碍功能<ExternalLinkIcon/></a>让一些身体有障碍的人可以方便地浏览你的 Web 应用。</p>
</li>
<li>
<p>监测并分析 Web 应用是否采实施了 SEO 搜素引擎优化 (<strong>SEO</strong>)。</p>
</li>
</ul>
<p>本文我们只需要关注 Web 应用的加载性能，所以勾选第一个 Performance 选项就可以了。</p>
<p>再看看<strong>设备 (Device) 部分</strong>，它给了我们两个选项，Moblie 选项是用来模拟移动设备环境的，另外一个 Desktop 选项是用来模拟桌面环境的。这里我们选择移动设备选项，因为目前大多数流量都是由移动设备产生的，所以移动设备上的 Web 性能显得更加重要。</p>
<p>配置好选项之后，我们就可以点击最上面的生成报告 (Generate report) 按钮来生成报告了。</p>
<h2 id="解读性能报告" tabindex="-1"><a class="header-anchor" href="#解读性能报告" aria-hidden="true">#</a> 解读性能报告</h2>
<p>点击生成报告的按钮之后，我们大约需要等待一分钟左右，Audits 就可以生成最终的分析报告了，如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/c0/22/c0420197cc60fb91af2f38903afc8022.png" alt="生成的报告图"></p>
<p>观察上图的分析报告，中间圆圈中的数字表示该站点在加载过程中的总体 Web 性能得分，总分是 100 分。我们目前的得分为 46 分，这表示该站点加载阶段的性能还有很大的提升空间。</p>
<p>Audits 除了生成性能指标以外，还会分析该站点并提供了很多优化建议，我们可以根据这些建议来改进 Web 应用以获得更高的得分，进而获得更好的用户体验效果。</p>
<p>既能分析 Web 性能得分又能给出优化建议，所以 Audits 的分析报告还是非常有价值的，那么接下来，我们就来解读下 Audits 生成的性能报告。</p>
<p>报告的第一个部分是<strong>性能指标 (Metrics)</strong>，如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/d2/26/d27cde1230afbabf6f914ee987c15026.png" alt="性能指标"></p>
<p>观察上图，我们可以发现性能指标下面一共有六项内容，这六项内容分别对应了从 Web 应用的加载到页面展示完成的这段时间中，各个阶段所消耗的时长。在中间还有一个 View Trace 按钮，点击该按钮可以跳转到 Performance 标签，并且查看这些阶段在 Performance 中所对应的位置。最下方是加载过程中各个时间段的屏幕截图。</p>
<p>报告的第二个部分是<strong>可优化项 (Opportunities)</strong>，如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/27/88/275dfab0e15ccf4f59e909e352197b88.png" alt="可优化项 (Opportunities)"></p>
<p>这些可优化项是 Audits 发现页面中的一些可以直接优化的部分，你可以对照 Audits 给的这些提示来优化你的 Web 应用。</p>
<p>报告的第三部分是<strong>手动诊断 (Diagnostics)</strong>，如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/1b/82/1bd988dde8315b1d286a5d72c0244d82.png" alt="手动诊断 (Diagnostics)"></p>
<p>在手动诊断部分，采集了一些可能存在性能问题的指标，这些指标可能会影响到页面的加载性能，Audits 把详情列出来，并让你依据实际情况，来手动排查每一项。</p>
<p>报告的最后一部分是<strong>运行时设置 (Runtime Settings)</strong>，如下图所示：</p>
<p><img src="https://static001.geekbang.org/resource/image/1a/7a/1a48f900ad3ce35371b92431d984507a.png" alt="运行时设置 (Runtime Settings)"></p>
<p>观察上图，这是运行时的一些基本数据，如果选择移动设备模式，你可以看到发送网络请求时的 User Agent 会变成设备相关信息，还有会模拟设备的网速，这个体现在网络限速上。</p>
<h2 id="根据性能报告优化-web-性能" tabindex="-1"><a class="header-anchor" href="#根据性能报告优化-web-性能" aria-hidden="true">#</a> 根据性能报告优化 Web 性能</h2>
<p>现在有了性能报告，接下来我们就可以依据报告来分析如何优化 Web 应用了。最直接的方式是想办法提高性能指标的分数，而性能指标的分数是由六项指标决定的，它们分别是：</p>
<ol>
<li>
<p>首次绘制 (First Paint)；</p>
</li>
<li>
<p>首次有效绘制 (First Meaningfull Paint)；</p>
</li>
<li>
<p>首屏时间 (Speed Index)；</p>
</li>
<li>
<p>首次 CPU 空闲时间 (First CPU Idle)；</p>
</li>
<li>
<p>完全可交互时间 (Time to Interactive)；</p>
</li>
<li>
<p>最大估计输入延时 (Max Potential First Input Delay)。</p>
</li>
</ol>
<p>那么接下来我会逐一分析六项指标的含义，并讨论如何提升这六项指标的数值。这六项都是页面在加载过程中的性能指标，所以要弄明白这六项指标的具体含义，我们还得结合页面的加载过程来分析。一图胜过千言，我们还是先看下面这张页面从加载到展示的过程图：</p>
<p><img src="https://static001.geekbang.org/resource/image/70/99/7041b4d913a12d4d53041e8ed8b30499.png" alt="页面加载过程"></p>
<p>观察上图的页面加载过程，我们发现，在渲染进程确认要渲染当前的请求后，渲染进程会创建一个空白页面，我们把创建空白页面的这个时间点称为 <strong>First Paint</strong>，简称 <strong>FP</strong>。</p>
<p>然后渲染进程继续请求关键资源，我们在《<a href="/guide/25" target="_blank" rel="noopener noreferrer">25｜页面性能：如何系统地优化页面？<ExternalLinkIcon/></a>》这节中介绍过了关键资源，并且知道了关键资源包括了 JavaScript 文件和 CSS 文件，因为关键资源会阻塞页面的渲染，所以我们需要等待关键资源加载完成后，才能执行进一步的页面绘制。</p>
<p>上图中，bundle.js 是关键资源，因此需要完成加载之后，渲染进程才能执行该脚本，然后脚本会修改 DOM，引发重绘和重排等一系列操作，当页面中绘制了第一个像素时，我们把这个时间点称为 <strong>First Content Paint</strong>，简称 <strong>FCP</strong>。</p>
<p>接下来继续执行 JavaScript 脚本，当首屏内容完全绘制完成时，我们把这个时间点称为 Largest Content Paint，简称 LCP。</p>
<p>在 FCP 和 LCP 中间，还有一个 FMP，这个是首次有效绘制，由于 FMP 计算复杂，而且容易出错，现在不推荐使用该指标，所以这里我们也不做过多介绍了。</p>
<p>接下来 JavaScript 脚本执行结束，渲染进程判断该页面的 DOM 生成完毕，于是触发 DOMContentLoad 事件。等所有资源都加载结束之后，再触发 onload 事件。</p>
<p>好了，以上就是页面在加载过程中各个重要的时间节点，了解了这些时间节点，我们就可以来聊聊性能报告的六项指标的含义并讨论如何优化这些指标。</p>
<p>我们先来分析下<strong>第一项指标 FP</strong>，如果 FP 时间过久，那么直接说明了一个问题，那就是页面的 HTML 文件可能由于网络原因导致加载时间过久，这块具体的分析过程你可以参考《<a href="/guide/21" target="_blank" rel="noopener noreferrer">21｜Chrome 开发者工具：利用网络面板做性能分析<ExternalLinkIcon/></a>》这节内容。</p>
<p><strong>第二项是 FMP</strong>，上面也提到过由于 FMP 计算复杂，所以现在不建议使用该指标了，另外由于 LCP 的计算规则简单，所以推荐使用 LCP 指标，具体文章你可以参考这里。不过是 FMP 还是 LCP，优化它们的方式都是类似的，你可以结合上图，如果 FMP 和 LCP 消耗时间过久，那么有可能是加载关键资源花的时间过久，也有可能是 JavaScript 执行过程中所花的时间过久，所以我们可以针对具体的情况来具体分析。</p>
<p><strong>第三项是首屏时间 (Speed Index)，这就是我们上面提到的 LCP</strong>，它表示填满首屏页面所消耗的时间，首屏时间的值越大，那么加载速度越慢，具体的优化方式同优化第二项 FMP 是一样。</p>
<p><strong>第四项是首次 CPU 空闲时间 (First CPU Idle)，也称为 First Interactive</strong>，它表示页面达到最小化可交互的时间，也就是说并不需要等到页面上的所有元素都可交互，只要可以对大部分用户输入做出响应即可。要缩短首次 CPU 空闲时长，我们就需要尽可能快地加载完关键资源，尽可能快地渲染出来首屏内容，因此优化方式和第二项 FMP 和第三项 LCP 是一样的。</p>
<p><strong>第五项是完全可交互时间 (Time to Interactive)，简称 TTI</strong>，它表示页面中所有元素都达到了可交互的时长。简单理解就这时候页面的内容已经完全显示出来了，所有的 JavaScript 事件已经注册完成，页面能够对用户的交互做出快速响应，通常满足响应速度在 50 毫秒以内。如果要解决 TTI 时间过久的问题，我们可以推迟执行一些和生成页面无关的 JavaScript 工作。</p>
<p><strong>第六项是最大估计输入延时 (Max Potential First Input Delay）</strong>，这个指标是估计你的 Web 页面在加载最繁忙的阶段， 窗口中响应用户输入所需的时间，为了改善该指标，我们可以使用 WebWorker 来执行一些计算，从而释放主线程。另一个有用的措施是重构 CSS 选择器，以确保它们执行较少的计算。</p>
<h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2>
<p>好了，今天的内容就介绍到这里，下面我来总结下本文的主要内容：</p>
<p>本文我们主要讨论如何优化加载阶段的 Web 应用的性能。</p>
<p>要想优化 Web 性能，首先得需要有 Web 应用的性能数据。所以接下来，我们介绍了 Chrome 采集 Web 性能数据的两个工具：Performance 和 Audits，Performance 可以采集非常多的性能，但是其使用难度大，相反，Audtis 就简单了许多，它会分析检测到的性能数据并给出站点的性能得分，同时，还会给我们提供一些优化建议。</p>
<p>我们先从简单的工具上手，所以本文我们主要分析了 Audits 的使用方式，先介绍了如何使用 Audits 生成性能报告，然后我们解读了性能报告中的每一项内容。</p>
<p>大致了解 Audits 生成的性能报告之后，我们又分析 Web 应用在加载阶段的几个关键时间点，最后我们分析性能指标的具体含义以及如何提高性能指标的分数，从而达到优化 Web 应用的目的。</p>
<p>通过介绍，我们知道了 Audits 非常适合用来分析加载阶段的 Web 性能，除此之外，Audits 还有其他非常实用的功能，比如可以检测我们的代码是否符合一些最佳实践，并给出提示，这样我们就可以根据 Audits 的提示来决定是否需要优化我们的代码，这个功能非常不错，具体使用方式留给你自己去摸索了。</p>
<h2 id="课后思考" tabindex="-1"><a class="header-anchor" href="#课后思考" aria-hidden="true">#</a> 课后思考</h2>
<p>在文中我们又分析 Web 应用在加载阶段的几个关键时间点，在 Audits 中，通过对这些时间点的分析，输出了文中介绍的六项性能指标，其实这些时间点也可以通过 Performance 的时间线 (Timelines) 来查看，那么今天留给你的任务是：提前熟悉下 Performance 工具，并对照这文中加载阶段的几个时间点来熟悉下 Performance 的时间线 (Timelines)，欢迎在留言区分享你的想法。</p>
<p>感谢阅读，如果你觉得这篇文章对你有帮助的话，也欢迎把它分享给更多的朋友。</p>
<h2 id="评论" tabindex="-1"><a class="header-anchor" href="#评论" aria-hidden="true">#</a> 评论</h2>
<p>卡尔：
原来 chrome v83.0.4103.61的Audits升级成Lighthouse了。</p>
</template>
